package cn.buk.tms.flight.service;

import cn.buk.common.JsonResult;
import cn.buk.common.dto.eterm.PnrDto;
import cn.buk.common.dto.eterm.PnrFlightDto;
import cn.buk.common.dto.eterm.TprInfoDto;
import cn.buk.common.dto.eterm.TprItemDto;
import cn.buk.tms.dao.FlightCharterDao;
import cn.buk.tms.dto.PatInfo;
import cn.buk.tms.entity.misc.EntDepartment;
import cn.buk.tms.entity.order.flight.FlightOrder;
import cn.buk.tms.entity.order.flight.FlightOrderPassenger;
import cn.buk.tms.entity.misc.TicketSale;
import cn.buk.qms.service.BaseFlightOrderService;
import cn.buk.tms.flight.request.FlightOrderRequestDto;
import cn.buk.tms.flight.util.FlightOrderUtil;
import cn.buk.common.util.BukEtermClient;
import cn.buk.common.util.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;

import static cn.buk.tms.flight.util.FlightOrderUtil.validateOrderInfoByAutoTicketing;

/**
 * @author yfdai
 */
@Service
public class BspEtermAutoTicketServiceImpl extends BaseFlightOrderService implements BspEtermAutoTicketService {

  private static final Logger logger = LogManager.getLogger(BspEtermAutoTicketServiceImpl.class);

  @Autowired
  public BspEtermAutoTicketServiceImpl(FlightCharterDao flightCharterDao) {
    this.flightCharterDao = flightCharterDao;
  }

  private final FlightCharterDao flightCharterDao;

  /**
   * 机票订单自动出票
   */
  @Override
  public void autoTicketFlightOrder(final int enterpriseId, final String username, final int orderId) {
    FlightOrder orderInfo = flightOrderDao.getOrderDetailById(orderId);
    if (orderInfo == null || enterpriseId != orderInfo.getEnterpriseId()) {
      throw new RuntimeException("FlightOrder is not existed.");
    }

    JsonResult jsonResult0 = validateOrderInfoByAutoTicketing(orderInfo);
    if (!JsonResult.STATUS_OK.equalsIgnoreCase(jsonResult0.getStatus())) {
      return ;
    }

    BukEtermClient eterm = null;
    try {
      eterm = borrowEtermClient(enterpriseId);
      final String pnrNo = orderInfo.getPnrNo();

      //获取第一屏的编码内容
      PnrDto pnrDto = execRt(enterpriseId, pnrNo, true, eterm);
      if (pnrDto == null) {
        return;
      }

      if (pnrDto.getDzStatus() == 1 && pnrDto.isEt()) {
        // 已出票，尝试回填票号
        // 出票完成，做收尾工作：分析票号并回填, 并获得TSL中的佣金
        fillFlightOrderAndCost(enterpriseId, username, orderId, pnrNo, orderInfo, 1, eterm);
        return;
      }

      //判断PNR的航段终态是否为HK
      if (!isFlightStatusHK(enterpriseId, pnrDto)) {
        return;
      }

      //xe命令移除不需要的项目
      execXeItems(enterpriseId, pnrDto, eterm);

      //使用pat:a命令，获取运价
      final String patItemCode = execPatAuto(enterpriseId, username, eterm, orderInfo);
      if (patItemCode == null) {
        return;
      }

      //执行sfc指令
      execCmdSfc(enterpriseId, pnrNo, patItemCode, eterm);

      // 做 RR
      execCmdRr(enterpriseId, pnrDto, eterm);

      //BSP 出票 etdz 出票
      int printCode = execBspEtdz(enterpriseId, pnrNo, eterm);

      if (printCode <= 0) {
        logger.error("print ticket failed.");
//        * -1: 表示缺少票号 -2: 表示打票机未建控 -3: 缺少FN项 -4：需要授权

        eterm.execCmd("IG");
        eterm.execCmd("XLOCK");

        String content = "其它自动出票错误";
        switch (printCode) {
          case -1:
            content = "打票机缺少票号";
            break;
          case -2:
            content = "打票机未建控";
            break;
          case -3:
            content = "缺少FN项";
            break;
          case -4:
            content = "需要授权";
            break;
          default:
            break;
        }
        flightOrderDao.appendFlightOrderLog(enterpriseId, username, orderId, content);

        return;
      }

      // 出票完成，做收尾工作：分析票号并回填, 并获得TSL中的佣金
      fillFlightOrderAndCost(enterpriseId, username, orderId, pnrNo, orderInfo, 1, eterm);
    } catch (Exception e) {
      e.printStackTrace();
      String content = "机票订单(" + orderInfo.getOrderNo() + ")在进行自动出票时发生意外情况，可能需要人工干预。" + e.getMessage();
      doSendAlert(enterpriseId, content, null, EntDepartment.DEPT_TICKETING);
    } finally {
      if (eterm != null) {
        try {
          eterm.execCmd("IG");
        } catch (UnsupportedEncodingException e) {
          e.printStackTrace();
        }

        returnEtermClient(enterpriseId, eterm);
      }
    }
  }

  private void execCmdRr(final int enterpriseId, final PnrDto pnrDto, final BukEtermClient eterm) throws UnsupportedEncodingException {
    String[] flightItemNos = pnrDto.getFlightItemNo().split("/");
    String rrCmd = null;
    for (String itemNo : flightItemNos) {
      rrCmd = rrCmd == null ? itemNo + "RR" : rrCmd + "\r" + itemNo + "RR";
    }
    doExecEtermCmd(enterpriseId, eterm, rrCmd);
  }

  private void execCmdSfc(final int enterpriseId, final String pnrNo, final String patItemCode, final BukEtermClient eterm) throws IOException {
    //执行SFC命令时，返回分为2此，一次返回空白，再返回PNR内容（带FC/A项），也有可能返回PLEASE WAIT WAIT。。。。
    String cmdResult = doExecEtermCmd(enterpriseId, eterm, "SFC:" + patItemCode);

    final Instant beginTime = Instant.now();
    while (true) {
      Duration duration = Duration.between(beginTime, Instant.now()).abs();
      if (duration.getSeconds() >= 10 || StringUtils.trimToEmpty(cmdResult).contains(pnrNo)) {
        break;
      }

      cmdResult = eterm.readAvailableData();
      if (cmdResult != null && cmdResult.length() > 7) {
        cmdResult = cmdResult.substring(7).replace("\r", "\r\n");
        logger.info(cmdResult);
      }
    }
  }

  private String execPatAuto(final int enterpriseId, final String username, final BukEtermClient eterm,
                             FlightOrder orderInfo) throws UnsupportedEncodingException {
    //使用订单中的大客户代码
    final String keyCustomerCode = StringUtils.trimToEmpty(orderInfo.getKeyCustomerNo());

    // 使用PAT:A       P价格
    String patCmd = "PAT:A"; //只显示5条
    if (keyCustomerCode.length() > 0) {
      patCmd += "#C" + keyCustomerCode;
    }
    patCmd += "/5";

    String cmdResult = doExecEtermCmd(enterpriseId, eterm, patCmd);

    String patItemCode = null;

    PatInfo patInfo = PatInfo.createByPatResponse(cmdResult);
    if (patInfo == null || patInfo.getCount() == 0) {
      doSendAlert(enterpriseId, "PAT:A出错了: " + cmdResult, null, EntDepartment.DEPT_TICKETING);
      return null;
    }

    logger.info("patInfo: " + patInfo.getCount());
    //如果设置了开票价格，就使用该值；否则默认使用订单中的成人票面价
    final int etdzFare = orderInfo.getAutoTicketingPrice() > 0 ? orderInfo.getAutoTicketingPrice()
            : (int) orderInfo.getPrice();

    if (patInfo.getCount() == 1) {
      return patInfo.getItemByIndex(0).getItemNo();
    }


    if (orderInfo.getAutoTicketing() == 1 && etdzFare < 1) {
      //将订单的自动出票状态设置为2：需要设置出票运价
      flightOrderDao.updateFlightOrderAutoTicketing(enterpriseId, username, orderInfo.getId(), 2, "需要设置开票价格");

      doSendAlert(enterpriseId, "请选择出票运价: " + cmdResult, null, EntDepartment.DEPT_TICKETING);
      return null;
    }
    if (orderInfo.getAutoTicketing() == 2 && etdzFare < 1) {
      doSendAlert(enterpriseId, "请选择出票运价: " + cmdResult, null, EntDepartment.DEPT_TICKETING);
      return null;
    }

    for (int i = 0; i < patInfo.getCount(); i++) {
      // 比较价格
      int fare = (int) patInfo.getItemByIndex(i).getFare();

      if (fare == etdzFare) {
        patItemCode = patInfo.getItemByIndex(i).getItemNo();
        break;
      }
    }


    if (patItemCode == null) {
      doSendAlert(enterpriseId, "未找到符合要求的PAT:A运价(" + orderInfo.getPnrNo() + ")", null, EntDepartment.DEPT_TICKETING);
    }

    return patItemCode;
  }

  /**
   * 开票时需要删除编码中一些不再需要的项目
   * @param enterpriseId
   * @param pnrDto
   * @param eterm
   * @throws UnsupportedEncodingException
   */
  private void execXeItems(final int enterpriseId, final PnrDto pnrDto, final BukEtermClient eterm) throws UnsupportedEncodingException {
    //删除必要的项目
    // 删除编码里携程相关的号码和OSI
    //XE 删除项目时，只能对当前屏上的内容进行操作
    //删除TL项
    String xeItems = pnrDto.getTktlItemNo();
    // 如果乘机人较多，要删除的项目一屏幕显示不下，就需要先删除当前页面能看见的，删除之后系统会显示最新的内容，接着删除需要删除的内容
    int loopCount = 0;

    while (xeItems != null) {
      String hostCmd = "XE:" + xeItems;
      //会返回删除对应项目后的编码内容
      String cmdResult = doExecEtermCmd(enterpriseId, eterm, hostCmd);

      PnrDto pnrDto1 = new PnrDto();
      pnrDto1.setPnrDetail(cmdResult);

      xeItems = pnrDto1.getTktlItemNo();

      loopCount++;
      if (loopCount >= 5) {
        logger.error("loopCount: " + loopCount);
        break;
      }
    }
  }

  private boolean isFlightStatusHK(final int enterpriseId, PnrDto pnrDto) {
    for(PnrFlightDto fltDto: pnrDto.getFlights()) {
      if (!"HK".equalsIgnoreCase(fltDto.getFlight().getSegmentStatus())) {
        String content = "航班" + fltDto.getFlight().getFlightNo()
                + "状态为" + fltDto.getFlight().getSegmentStatus()
                + "，需要HK。" ;
        doSendAlert(enterpriseId, content, null, EntDepartment.DEPT_TICKETING);
        return false;
      }
    }
    return true;
  }

  /**
   * 调取编码内容，并返回符合开票要求的对象
   * @param enterpriseId
   * @param pnrNo
   * @param needIg
   * @param eterm
   * @return 符合开票要求的PnrDto对象
   * @throws UnsupportedEncodingException
   * @throws InterruptedException
   */
  private PnrDto execRt(final int enterpriseId, final String pnrNo, final boolean needIg, BukEtermClient eterm)
          throws UnsupportedEncodingException, InterruptedException {

    if (needIg) {
      doExecEtermCmd(eterm, "IG");
      Thread.sleep(1000);
    }

    String pnrDetail = doExecEtermCmd(eterm, "RT:" + pnrNo);

    if (pnrDetail == null) {
      return null;
    }

    if (pnrDetail.contains("系统忙线中")) {
      doSendAlert(enterpriseId, "系统忙线中", null, EntDepartment.DEPT_TICKETING);
      return null;
    }

    //NEED EOT -- 需要封口(@)或还原(IG)
    if (pnrDetail.contains("NEED EOT -- 需要封口(@)或还原(IG)")) {
      Thread.sleep(500);
      doExecEtermCmd(enterpriseId, eterm, "IG");

      Thread.sleep(500);
      pnrDetail = doExecEtermCmd(enterpriseId, eterm, "RT:" + pnrNo);
    }

    if (pnrDetail != null && pnrDetail.contains("需要授权")) {
      doSendAlert(enterpriseId, "需要授权", null, EntDepartment.DEPT_TICKETING);
      return null;
    }

    PnrDto pnrDto = new PnrDto();
    pnrDto.setPnrDetail(pnrDetail);

    if (pnrDto.getFlightNo() == null) {
      doSendAlert(enterpriseId, "获取内容出错了，请稍后重试: " + pnrDetail + ".", null, EntDepartment.DEPT_CUSTOMER_SERVICE);
      return null;
    }

    if (pnrDto.getDzStatus() == 1) {
      if (pnrDto.isEt()) {
        // 编码已出票，分析票号并回填
        doSendAlert(enterpriseId, pnrNo + " 已出票", null, EntDepartment.DEPT_TICKETING);
        return pnrDto;
      } else {
        eterm.execCmd("IG");
        eterm.execCmd("XLOCK");
        doSendAlert(enterpriseId, "已出，未成功，请稍后重试: " + pnrDetail, null,
                EntDepartment.DEPT_TICKETING);
        return null;
      }
    }

    // 判断航段状态，如果是NO状态，则退出出票过程
    if (pnrDto.getSegCount() > 0 && "NO".equalsIgnoreCase(pnrDto.getSegStatus())) {
      doSendAlert(enterpriseId, pnrDetail, null, EntDepartment.DEPT_TICKETING);
      return null;
    }

    return pnrDto;
  }

  /**
   *将票号回填订单，并获取成本
   * @param enterpriseId
   * @param username
   * @param pnrNo
   * @param orderInfo
   * @param eterm
   */
  private void fillFlightOrderAndCost(final int enterpriseId, final String username, final int orderId, final String pnrNo,
                                      FlightOrder orderInfo, final int smsMode, BukEtermClient eterm) throws IOException {
    JsonResult jsonResult = updateFlightOrderTicketNo(enterpriseId, username, pnrNo, orderInfo, smsMode,
            eterm);

    if (JsonResult.STATUS_OK.equalsIgnoreCase(jsonResult.getStatus())) {

      //获取订单的成本
      int retCode = updateFlightOrderCost(enterpriseId, username, orderId, eterm);
      if (retCode != 1) {
        String content1 = "机票订单(" + orderInfo.getOrderNo() + ")获取佣金失败。";
        doSendAlert(enterpriseId, content1, null, EntDepartment.DEPT_TICKETING);
        //TODO 超过10分钟，则修改为非自动出票
      } else {
        // 完成订单
        doFinishFlightOrder(enterpriseId, username, orderId);
      }
    }
  }

  private JsonResult updateFlightOrderTicketNo(final int enterpriseId, final String username,
                                               final String pnrNo, final FlightOrder orderInfo, final int smsMode, final BukEtermClient eterm)
          throws IOException {
    // 重新调取编码，查看是否有票号
    String pnrDetail = execEtermCmdRt(eterm, pnrNo);
    if (pnrDetail == null || pnrDetail.trim().length() == 0) {
      try {
        Thread.sleep(5000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }

      pnrDetail = execEtermCmdRt(eterm, pnrNo);
    }
    PnrDto pnrDto = new PnrDto();
    pnrDto.setPnrDetail(pnrDetail);

    eterm.execCmd("IG");
    eterm.execCmd("XLOCK");

    if (pnrDto.isEt() && pnrDto.getDzStatus() == 1) {

      // 处理获取票号的情况
      for (FlightOrderPassenger psgInfo : orderInfo.getPassengers()) {
        String psgName = psgInfo.getPsgName();
        String ticketNo = pnrDto.getTicketNoByName(psgName);
        if (ticketNo == null || ticketNo.trim().length() < 13) {
          // 通过姓名获取票号失败，试试证件号
          ticketNo = pnrDto.getTicketNoByIdNo(psgInfo.getIdNo());
          if (ticketNo != null && ticketNo.trim().length() > 10) {
            doSendAlert(enterpriseId, "通过证件号(" + psgInfo.getIdNo() + ")获取票号(" + ticketNo + ")",
                    null, EntDepartment.DEPT_ADMINISTRATOR);
          }
        }

        if (ticketNo != null && ticketNo.trim().length() >= 13) {
          ticketNo = ticketNo.trim();
          psgInfo.setTicketNo(ticketNo);
        }
      }

      return execUpdateTicketNo(enterpriseId, username, orderInfo, smsMode);

    } else {
      final String content = "请等待出票完成(" + pnrDetail + ")";
      doSendAlert(enterpriseId, content, null, EntDepartment.DEPT_TICKETING);
      return JsonResult.createJsonResult(-101, content);
    }
  }

  /**
   * 获取订单的成本 通过TSL获取代理费，然后计算成本，并保存
   * 或通过接口获取
   */
  private int updateFlightOrderCost(final int enterpriseId, final String username,
                                    final int flightOrderId, final BukEtermClient eterm) {
    try {
      doExecTsl(enterpriseId, eterm);
      //TODO 若TSL获取得到的票号的佣金为0，需要通过其它途径校验
      //有新票号保存了，试试去获取佣金
      // 没有新票号保存也有可能，之前已经保存过了
      FlightOrder flightOrder = flightOrderDao.getOrderDetailById(flightOrderId);

      final String ticketNo = flightOrder.getPassengers().get(0).getTicketNo();
      if (ticketNo == null || ticketNo.trim().length() < 13 || ticketNo.trim().length() > 14) {
        logger.warn("need valid ticket No.");
        return 0;
      }

      //查找出票记录
      TicketSale ticketSale = flightCharterDao.getTicketSaleByTicketNo(enterpriseId, ticketNo, 0);
      if (ticketSale == null) {
        logger.warn("need ticket sale info.");
        return 0;
      }

      if (ticketSale.getCommission() < 0) {
        logger.warn("commission must be >= 0");
        return 0;
      }

      //获取到了佣金，计算机票订单的成本
      FlightOrderRequestDto dto = FlightOrderUtil.createDtoByFlightOrder(flightOrder);

      //校验价格和税收是否相等
      final int price0 = (int) dto.getAdultPrice().getPrice();
      final int price1 = (int) ticketSale.getPrice();
      final int tax0 = (int) dto.getAdultPrice().getTax();
      final int tax1 = (int) ticketSale.getTax();
      if (price0 != price1 || tax0 != tax1) {
        //记录日志
        final String content = ticketNo + ": " + price0 + " ?= " + price1 + ", " + tax0 + " ?= " + tax1;
        flightOrderDao.appendFlightOrderLog(enterpriseId, username, flightOrderId, content);
        doSendAlert(enterpriseId, content, null, EntDepartment.DEPT_ADMINISTRATOR);
        return 0;
      }

      if (ticketSale.getCommission() >= 100) {
        //报错
        final String content = ticketNo + ": 获取佣金金额(" + ticketSale.getCommission() + ")出错";
        doSendAlert(enterpriseId, content, null, EntDepartment.DEPT_TICKETING);
        return 0;
      }

      if (ticketSale.getCommission() < 0.001) {
        final String content = "提醒：" + ticketNo + "佣金为" + ticketSale.getCommission();
        doSendAlert(enterpriseId, content, null, EntDepartment.DEPT_TICKETING);
      }


      dto.getAdultPrice().setCommission(ticketSale.getCommission());

      return flightOrderDao.updatePrice(enterpriseId, username, flightOrderId, dto);
    } catch (UnsupportedEncodingException ex) {
      logger.error(ex.getMessage());
      return -100;
    }
  }

  /**
   * 执行BSP出票
   *
   * @return 大于0的数，表示出票成功；小于0，表示出错的原因
   *
   * -1: 表示缺少票号 -2: 表示打票机未建控 -3: 缺少FN项 -4：需要授权
   */
  private int execBspEtdz(final int enterpriseId, final String pnrNo, final BukEtermClient eterm)
          throws IOException {
    final int printerNo = enterpriseDao.getBspPrinterNo(enterpriseId);
    final String etdzCmd = "ETDZ " + printerNo;
    String cmdResult = doExecEtermCmd(enterpriseId, eterm, etdzCmd);

    // 判断指令结果，是否出票成功
    int retCode = 0;

    final Instant beginTime = Instant.now();
    while (true) {
      if (cmdResult != null) {
        retCode = processEtdzResponse(enterpriseId, pnrNo, cmdResult, printerNo, eterm);
        if (retCode == 0) {
          doSendAlert(enterpriseId, pnrNo + ": " + "cmdResult: " + cmdResult, null, EntDepartment.DEPT_TICKETING);
        }
        break;
      }

      // 等待时间超过10秒，或成功
      if (Duration.between(beginTime, Instant.now()).abs().getSeconds() >= 10) {
        break;
      }

      cmdResult = eterm.readAvailableData();
    }

    return retCode;
  }

  private int processEtdzResponse(final int enterpriseId, final String pnrNo, final String cmdResult,
                                  final int printerNo, final BukEtermClient eterm) throws UnsupportedEncodingException {
    if (cmdResult.contains(pnrNo)) {
      return 1;
    }

    if (cmdResult.contains("NOT ENOUGH TICKET NUMBERS ASSIGNED TO DEVICE")
            || "STOCK".equalsIgnoreCase(cmdResult.trim())
    ) {
      doSendAlert(enterpriseId, pnrNo + ": " +"打票机(" + printerNo + ")缺少票号: " + cmdResult, null,
              EntDepartment.DEPT_TICKETING);
      doExecEtermCmd(enterpriseId, eterm, "DI " + printerNo);

      return  -1;
    } else if ("INACTIVE".equalsIgnoreCase(cmdResult)) {
      //打票机需要建立控制
      doSendAlert(enterpriseId, pnrNo + ": " + "打票机未处于活动状态: " + cmdResult, null, EntDepartment.DEPT_TICKETING);

      return  -2;
    } else if ("INCOMPLETE PNR/FN".equalsIgnoreCase(cmdResult.trim())) {
      //出票时需要的信息不完整，没有FN项
      doSendAlert(enterpriseId, pnrNo + ": " +"INCOMPLETE PNR/FN", null, EntDepartment.DEPT_TICKETING);

      return  -3;
    } else if (cmdResult.contains("PNR TICKETED")) {
      // 表示已经出过票了
      return  2;
    } else if (cmdResult.contains("需要授权")) {
      doSendAlert(enterpriseId, pnrNo + ": ETDZ时返回:" + cmdResult, null, EntDepartment.DEPT_TICKETING);
      return  -4;
    }

    return 0;
  }

  private String execEtermCmdRt(BukEtermClient eterm, final String pnrNo) throws IOException {
    // 提取PNR
    String pnrDetail = null;

    int tryCount = 0;

    final Instant beginTime = Instant.now();
    while (true) {
      tryCount++;
      logger.info("****** rt ****** " + tryCount);
      pnrDetail = eterm.rt(pnrNo);
      pnrDetail = pnrDetail.replace("\r", "\r\n");
      logger.info(pnrDetail);

      if (pnrDetail.contains(pnrNo)) {
        break;
      }

      Duration duration = Duration.between(beginTime, Instant.now()).abs();
      if (duration.getSeconds() >= 10) {
        break;
      }

      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        logger.error(e.getMessage());
      }
      eterm.readAvailableData();
    }

    return pnrDetail;
  }

  private void execTsl(final int enterpriseId) {
    BukEtermClient eterm = null;
    try {
      eterm = borrowEtermClient(enterpriseId);
      doExecTsl(enterpriseId, eterm);
    } catch (Exception e) {
      e.printStackTrace();
      String content = "TSL在进行时发生意外情况" + e.getMessage();
      doSendAlert(enterpriseId, content, "Dai", 0);
    } finally {
      returnEtermClient(enterpriseId, eterm);
    }
  }

  /**
   * TSL最近的10个票号, 并保存
   */
  private void doExecTsl(final int enterpriseId, BukEtermClient eterm)
          throws UnsupportedEncodingException {
    final int printerNo = enterpriseDao.getBspPrinterNo(enterpriseId);

    String hostcmd = "TSL:" + printerNo;
    boolean cmdDone = false;
    final StringBuilder cmdresult = new StringBuilder();

    int loopCount = 0;
    while (!cmdDone) {

      String rs0 = eterm.execCmd(hostcmd);
      if (rs0 == null) {
        loopCount++;
        if (loopCount >= 10) {
          break;
        } else {
          continue;
        }
      }
      loopCount = 0;

      if (cmdresult.length() == 0) {
        cmdresult.append(rs0.substring(7));
      } else {
        cmdresult.append("\r").append(rs0.substring(7));
      }

      cmdDone = !rs0.endsWith("+");
      hostcmd = "PN";

      try {
        if (!cmdDone) {
          Thread.sleep(500);
        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    if ("DEVICE".equalsIgnoreCase(cmdresult.toString().trim())) {
      return;
    }

    if ("NO DATA".equalsIgnoreCase(cmdresult.toString().trim())) {
      return;
    }

    //保存TPR/TSL结果
    TprInfoDto tprInfo = new TprInfoDto();
    tprInfo.setCmdResult(cmdresult.toString());

    int deviceId0 = 0;
    try {
      deviceId0 = Integer.parseInt(tprInfo.getDeviceId());
    } catch (Exception ex) {
      return;
    }
    if (deviceId0 != printerNo) {
      return;
    }

    if (tprInfo.getTicketCount() != tprInfo.getTotalTicket()) {
      logger.warn(
              "tpr warning: total ticket is not equal ticket count（" + tprInfo.getTotalTicket() + ", "
                      + tprInfo.getTicketCount());
    }

    List<TicketSale> tickets = new ArrayList<>();

    for (TprItemDto item : tprInfo.getItems()) {
      TicketSale ticket = new TicketSale();
      ticket.setEnterpriseId(enterpriseId);
      tickets.add(ticket);

      BeanUtils.copyProperties(item, ticket);

      ticket.setSellDate(DateUtil.getCurDate());
      ticket.setDeviceId(printerNo);
      ticket.setOfficeNo(tprInfo.getOfficeNo());
      ticket.setStatus(0);
      ticket.setTicketStatus(item.getStatus());
    }

    flightCharterDao.createTicketSales(tickets);
  }

  /**
   * 执行德付通出票
   */
  private int execDpayEtdz(final int enterpriseId, final String pnrNo, final String dpayPassword,
                           final BukEtermClient eterm) throws UnsupportedEncodingException {
    int retCode = 0;
    doSendAlert(enterpriseId, "德付通出票", null, EntDepartment.DEPT_OTA_CTRIP);

    String cmdResult = null;
    // DPAY: 123456     123456是密码
    doExecEtermCmd(enterpriseId, eterm, "DPAY:" + dpayPassword); // 指令正确返回的结果为当前处理的编码内容

    // ETDZ D           德付通出票
    cmdResult = doExecEtermCmd(enterpriseId, eterm, "ETDZ:D");

    if (cmdResult.contains(pnrNo)) {
      //返回以下的结果表示出票成功
//            CNY6540.00      HXKK3G
//            836-3175422698         836-3175422700
      retCode = 1;
    }

    doSendAlert(enterpriseId, cmdResult, null, EntDepartment.DEPT_OTA_CTRIP);

    return retCode;
  }

}
